#define _GNU_SOURCE 1

#include <stdio.h>
#include <stdlib.h>  // malloc/calloc
#include <stdbool.h>
#include <regex.h>
#include <string.h>
#include <assert.h>

#define MAX_VARIABLE_NAME 16
#define MAX_LINE_LENGTH 128
#define VARIABLE_BASE_LENGTH 6


//struct declarations

//2 dimensional nodes
// aka node1 -> node2 -> node3 -> node4 -> etc.
//      ||        ||       ||       ||
//      \/        \/       \/       \/
//     node1     node2    node2    node3

typedef struct d2node * d2nodeptr;
typedef struct d2node {
  bool multiple_variables;
  struct d2node * right;  // the next node
  struct d2node * left;
  struct d2node * bottom;  // this is the start of another linear list.  Each item in the list contains a reference to the variable name
  struct d2node * top;  //this is how one can crawl back up the 2 dimensional node
  char variable_name [MAX_VARIABLE_NAME];
} d2node;


/* technically this is just lazy code. but who cares? */
void * xmalloc (size_t size);
  
d2nodeptr allocate_new_d2node ();

/* this returns the address of the first created
   d2node.
*/
d2nodeptr address_of_first_d2node (d2nodeptr nodep);

/* Returns the start of the variable name
** input:         "int purple = 5;"
** return: pointer to  ^
*/
// this function could probably be replace by a regex
//THIS function is also NOT working.  So that's annoying
//It also causes length_of_varable name to not work either
char * start_of_variable_name (char * line);

/* Returns the end of the variable name
** input:   "int purple = 5;"
** return: pointer to ^
*/
char * end_of_variable_name (char * line);

int length_of_variable_name (char * start, char * end);

/* This function checks the string against our common
 * variable name bases.  If we have seen this variable's
 * base name (the first 6 letters) before, then we
 * return the pointer to the beginning of the column
 * where it exists
 * ie:  if variable name is purple_7 and the 2 dimensional
 * nodes look like
 *  blacke  =>  greens  =>  purple 
 *    ||          ||          ||
 *    \/          \/          \/
 *  blacke_s    greens_a    purple_1
 *
 * then this function will return the d2nodeptr to the
 * "purple" node
 **/
d2nodeptr is_this_variable_base_unique (char * string);

/*  */
void add_new_variable_base (char * string, int length);
/*
 * this function should be called after is_this_variable_base_unique
 * this function checks the current
 *
 */
d2nodeptr is_this_a_new_variable (char * string, int length);

void store_c_file_common_variables (FILE * input_file_stream);

void print_common_base_name_variables ();

/*
** This function should be called after, store_c_file_common_variables
** 
** It prints all the variable names in the 2deminsional datastructure.
** 
** It is a naive implementation.  nodep ends up pointing at the end of the
** datastructure.  So you cannot call this function twice
**
** THE PROBLEM IS HERE. FIXME!  The store variables datastrure is storing data
** fine. BUT THIS function is NOT PRINTING THEM!
**
*/
void print_c_file_common_variables ();
